/* 
 *   Copyright (c) Microsoft Corporation.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Microsoft Corporation nor the names of its contributors 
 *       may be used to endorse or promote products derived from this software
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Mvc;
using Ogdi.InteractiveSdk.Mvc.App_GlobalResources;
using Ogdi.InteractiveSdk.Mvc.Models;
using Ogdi.InteractiveSdk.Mvc.Repository;

namespace Ogdi.InteractiveSdk.Mvc.Controllers
{
    [HandleError]
    public class DataCatalogController : Controller
    {

        #region Private Members

        private DataCatalogModel viewDataModel = new DataCatalogModel();

        #endregion

        #region DataCatalog Static Members

        // Hashtable to store ContainerAlias & ContainerDisclaimer
        static Hashtable hashAliasDisclaimer;

        #endregion

        #region DataCatalog Public Methods

        /// <summary>
        /// This action provides required ViewData for loading DataCatalog page
        /// </summary>
        /// <returns>Returns view with all necessary data</returns>          
        public ActionResult Index()
        {
            HideError();          

            try
            {
                // Fetch all Containers
                string currentContainer = SetContainerList();
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
          
            ViewData.Model = viewDataModel;

            return View();
        }

        /// <summary>
        /// This action provides necessary ViewData for showing categories and entitySets on the page 
        /// according to passed parameters
        /// </summary>
        /// <param name="containerAlias">Container in string format</param>
        /// <param name="entitySetName">EnitySet name in string format.</param>
        /// <returns>PartialView-DataCategories with neccessay data required for its rendering</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult LoadDataCatalogByContainerAlias(string containerAlias, string entitySetName)
        {
            HideError();
            try
            {
                // Fetch all Categories & EntitySets                
                SetCategoryListAndEntitySets(containerAlias, entitySetName);
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
            ViewData.Model = viewDataModel;
            return PartialView("DataCategories", ViewData.Model);
        }

        /// <summary>
        /// This action provides necessary ViewData for showing entitySets on the page 
        /// according to passed parameters
        /// </summary>
        /// <param name="containerAlias">Container name in string format</param>
        /// <param name="categoryName">Category name in string format</param>
        /// <returns>PartialView-EntitySets with neccessay data required for its rendering</returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult LoadEntitySetsByCategory(string containerAlias, string categoryName)
        {
            HideError();
            try
            {
                // Check for 'All' category selection
                if (!string.IsNullOrEmpty(categoryName))
                {
                    if (categoryName == UIConstants.DCPC_All)
                    {
                        // Fetch all EntitySets for the currentContainer
                        // for all categories
                        SetEntitySets(containerAlias, null);
                    }
                    else
                    {
                        // Fetch all EntitySets for the currentContainer
                        // and passed CategoryName
                        SetEntitySets(containerAlias, categoryName);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
             ViewData.Model = viewDataModel;
            return PartialView("EntitySets", ViewData.Model);
        }

        /// <summary>
        /// This actions returns the legal disclaimer text in json format
        /// </summary>
        /// <param name="containerAlias">Container name in string format</param>
        /// <returns>Returns JsonResult of the Legal Disclaimer text</returns>
        public JsonResult ReturnLegalDisclaimerForThisAlias(string containerAlias)
        {
            HideError();

            // Declare a variable of type List<string>
            List<string> LegalDisclaimer = null;

            // Gets Legal Disclaimer for the passed containerAlias
            try
            {
                // Define LegalDisclaimer
                LegalDisclaimer = new List<string>();

                // Add to Legal Disclaimer to the LegalDisclaimer
                LegalDisclaimer.Add(hashAliasDisclaimer[containerAlias].ToString());
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }

            return new JsonResult
            {
                Data = LegalDisclaimer,
            };
        }

        #endregion

        #region DataCatalog Private Methods

        /// <summary>
        /// This method fetches all Containers &
        /// sets the result to viewDataModel.ContainerList
        /// </summary>
        /// <returns>Current container</returns>
        private string SetContainerList()
        {
            // Get the list of Container object in a variable 
            // containerList of the type List<Container> 
            List<Container> containerList = new List<Container>();

            // Declate a variable of the type SelectList
            SelectList containersSelectList = new SelectList(containerList);
            string currentContainer = null;

            try
            {
                // Get the container list
                containerList = (List<Container>)ContainerRepository.GetAllContainers();

                // Set currentContainer to the first element of the list
                currentContainer = containerList[0].Alias;

                // Converts List<Container> to SelectList
                containersSelectList = new SelectList(containerList,
                UIConstants.ContainerComboBoxKeyAttribute,
                UIConstants.ContainerComboBoxValueAttribute,
                currentContainer);

                // Load hashtable hashAliasDisclaimer with key=Alias & value=Disclaimer
                if (hashAliasDisclaimer == null || hashAliasDisclaimer.Count == 0)
                {
                    hashAliasDisclaimer = new Hashtable();

                    // Fill the disclaimers in the hashtable
                    foreach (Container container in containerList)
                    {
                        hashAliasDisclaimer.Add(container.Alias, container.Disclaimer);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }

            // Set viewDataModel.ContainerList
            viewDataModel.ContainerList = containersSelectList;

            return currentContainer;
        }

        /// <summary>
        /// Fetches all Categories & Entity Sets for the passes 
        /// containerAlias and categoryName & 
        /// set the result to viewDataModel.CategoryList and viewDataModel.EntitySet
        /// </summary>
        /// <param name="containerAlias">Alias of the Container</param>
        /// <param name="categoryName">Name of the Category</param>
        private void SetCategoryListAndEntitySets(string containerAlias,
            string categoryName)
        {
            try
            {
                // Set viewDataModel.CategoryName
                // Chack for 'All' categories
                if (string.IsNullOrEmpty(categoryName) ||
                    categoryName.Equals(UIConstants.DCPC_All) ||
                    categoryName.Equals(UIConstants.DCPC_AllDataSetsText))
                {
                    viewDataModel.CategoryName = UIConstants.DCPC_AllDataSetsText;
                    categoryName = null;
                }
                else
                {
                    viewDataModel.CategoryName = categoryName;
                }

                // Define a variable of type List<EntitySet>
                List<EntitySet> lstEntitySets = new List<EntitySet>();
                
                // Get data from service
                lstEntitySets = EntitySetRepository.GetEntitySets(containerAlias, null) as List<EntitySet>;                    

                // Set viewDataModel.CategoryList
                viewDataModel.CategoryList = FetchCategories(lstEntitySets);

                // Set viewDataModel.EntitySet
                if (!string.IsNullOrEmpty(categoryName))
                {
                    // Get Entitysets for the specific category                    
                    viewDataModel.EntitySet = FetchCategorizedEntitySets(categoryName, lstEntitySets);                          

                }
                else
                {
                    // Get all Entitysets                    
                    viewDataModel.EntitySet = lstEntitySets;
                }
            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
        }

        /// <summary>
        /// Fetches all Entity Sets for the passes containerAlias and 
        /// categoryName & set the result to viewDataModel.EntitySet
        /// </summary>
        /// <param name="containerAlias">Alias of the Container</param>
        /// <param name="categoryName">Name of the Category</param>
        private void SetEntitySets(string containerAlias, string categoryName)
        {
            try
            {
                if (categoryName == null)
                {
                    // Set viewDataModel.CategoryName
                    viewDataModel.CategoryName = UIConstants.DCPC_AllDataSetsText;
                }
                else
                {
                    // Set viewDataModel.CategoryName
                    viewDataModel.CategoryName = categoryName;
                }

                // Define a variable of type List<EntitySet>
                List<EntitySet> lstEntitySets = new List<EntitySet>();

                
                    // Get data from service
                    lstEntitySets = EntitySetRepository.GetEntitySets(
                        containerAlias, categoryName) as List<EntitySet>;
                 

                // Set viewDataModel.EntitySet
                viewDataModel.EntitySet = lstEntitySets;

            }
            catch (Exception ex)
            {
                ShowError(ex.Message);
            }
        }

        /// <summary>
        /// This method is called when error/exception occurs
        /// This method will set the value of viewDataModel.ErrorLine1
        /// and viewDataModel.ErrorLine2
        /// </summary>
        /// <param name="detail">details of an error</param>
        private void ShowError(string detail)
        {
            // Set the error ViewData
            viewDataModel.ErrorLine1 = UIConstants.GC_ErrorString;
            viewDataModel.ErrorLine2 = detail;
        }

        /// <summary>
        /// This method is called when a page is newly loaded
        /// This method will reset the value of viewDataModel.ErrorLine1
        /// and viewDataModel.ErrorLine2
        /// </summary>
        private void HideError()
        {
            // Reset the error ViewData
            viewDataModel.ErrorLine1 = string.Empty;
            viewDataModel.ErrorLine2 = string.Empty;
        }

        /// <summary>
        /// This method fetches the distinct categories from the
        /// list of EntitySets
        /// </summary>
        /// <param name="lstEntitySets">List of EntitySets</param>
        /// <returns>List of categories</returns>
        private static List<string> FetchCategories(List<EntitySet> lstEntitySets)
        {
            // Get unique categories
            return ((from category in lstEntitySets
                     orderby category.CategoryValue
                     select category.CategoryValue).Distinct())
                                 .ToList<string>();
        }

        /// <summary>
        /// This method fetches the entitysets of category equals
        /// to passed categoryName
        /// </summary>
        /// <param name="categoryName">name of the category</param>
        /// <param name="lstEntitySets">list of EntitySets</param>
        /// <returns>list of Entity Sets with category equals to passed
        /// categoryName </returns>
        private static List<EntitySet> FetchCategorizedEntitySets(string categoryName,
            List<EntitySet> lstEntitySets)
        {
            // Get entitySets with the specific category
            if (!string.IsNullOrEmpty(categoryName))
            {
                return (from entitySet in lstEntitySets
                        where entitySet.CategoryValue == categoryName
                        select entitySet).ToList<EntitySet>();
            }
            else
            {
                return (from entitySet in lstEntitySets
                        select entitySet).ToList<EntitySet>();
            }
        }

        #endregion
    }
}
